﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using EDSDKLib;

namespace Canon
{
    public partial class MainForm : Form
    {
        SDKHandler CameraHandler;
        List<int> AvList;
        List<int> TvList;
        List<int> ISOList;
        List<Camera> CamList;
        int LiveViewWidth = 1024;
        int LiveViewHeight = 680;

        public MainForm()
        {
            InitializeComponent();
            CameraHandler = new SDKHandler();
            CameraHandler.CameraAdded += new SDKHandler.CameraAddedHandler(SDK_CameraAdded);
            CameraHandler.FrameRateUpdated += new SDKHandler.FloatUpdate(SDK_FrameRateUpdated);
            CameraHandler.LiveViewUpdated += new SDKHandler.ImageUpdate(SDK_LiveViewUpdated);
            CameraHandler.ProgressChanged += new SDKHandler.ProgressHandler(SDK_ProgressChanged);
            CameraHandler.CameraHasShutdown += CameraHandler_CameraHasShutdown;
            SavePathTextBox.Text = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "RemotePhoto");
            RefreshCamera();
        }


        private void SDK_ProgressChanged(int Progress)
        {
        }

        private void SDK_LiveViewUpdated(Image img)
        {
            LiveViewWidth = img.Width;
            LiveViewHeight = img.Height;
            if (CameraHandler.IsLiveViewOn) LiveViewPicBox.Image = img;
            else LiveViewPicBox.Image = null;
        }

        private void SDK_FrameRateUpdated(float Value)
        {
            this.Invoke((MethodInvoker)delegate { FrameRateLabel.Text = "FPS: " + Value.ToString("F2"); });
        }

        private void SDK_CameraAdded()
        {
            RefreshCamera();
        }

        private void CameraHandler_CameraHasShutdown(object sender, EventArgs e)
        {
            CloseSession();
        }


        private void SessionButton_Click(object sender, EventArgs e)
        {            
            if (CameraHandler.CameraSessionOpen)
                CloseSession();
            else 
                OpenSession();
        }

        private void RefreshButton_Click(object sender, EventArgs e)
        {
            RefreshCamera();
        }


        private void LiveViewButton_Click(object sender, EventArgs e)
        {
            if (!CameraHandler.IsEvfFilming)
            {
                if (!CameraHandler.IsLiveViewOn) { CameraHandler.StartLiveView(); LiveViewButton.Text = "Stop LiveView"; }
                else { CameraHandler.StopLiveView(); LiveViewButton.Text = "Start LiveView"; }
            }
        }

        private void RecordEfvButton_Click(object sender, EventArgs e)
        {
            if (!CameraHandler.IsEvfFilming && !CameraHandler.IsLiveViewOn) { SettingsGroupBox.Enabled = false; CameraHandler.StartEvfFilming(); RecordEvfButton.Text = "Stop Recording"; }
            else if (CameraHandler.IsEvfFilming) { SettingsGroupBox.Enabled = true; CameraHandler.StopEvfFilming(); RecordEvfButton.Text = "Start Recording"; }
        }

        private void LiveViewPicBox_MouseDown(object sender, MouseEventArgs e)
        {
            CameraHandler.SetManualWBEvf((ushort)((e.X / 270d) * LiveViewWidth), (ushort)((e.Y / 180d) * LiveViewHeight));
        }

        private void FocusNear3Button_Click(object sender, EventArgs e)
        {
            CameraHandler.SetFocus(EDSDK.EvfDriveLens_Near3);
        }

        private void FocusNear2Button_Click(object sender, EventArgs e)
        {
            CameraHandler.SetFocus(EDSDK.EvfDriveLens_Near2);
        }

        private void FocusNear1Button_Click(object sender, EventArgs e)
        {
            CameraHandler.SetFocus(EDSDK.EvfDriveLens_Near1);
        }

        private void FocusFar1Button_Click(object sender, EventArgs e)
        {
            CameraHandler.SetFocus(EDSDK.EvfDriveLens_Far1);
        }

        private void FocusFar2Button_Click(object sender, EventArgs e)
        {
            CameraHandler.SetFocus(EDSDK.EvfDriveLens_Far2);
        }

        private void FocusFar3Button_Click(object sender, EventArgs e)
        {
            CameraHandler.SetFocus(EDSDK.EvfDriveLens_Far3);
        }


        private void TakePhotoButton_Click(object sender, EventArgs e)
        {
            if ((STComputerButton.Checked || STBothButton.Checked) && !Directory.Exists(SavePathTextBox.Text)) Directory.CreateDirectory(SavePathTextBox.Text);
            CameraHandler.ImageSaveDirectory = SavePathTextBox.Text;
            if ((string)TvCoBox.SelectedItem == "Bulb") CameraHandler.TakePhoto((uint)BulbUpDo.Value);
            else CameraHandler.TakePhoto();
        }

        private void RecordVideoButton_Click(object sender, EventArgs e)
        {
            if (!CameraHandler.IsFilming)
            {
                if (STComputerButton.Checked || STBothButton.Checked)
                {
                    if (!Directory.Exists(SavePathTextBox.Text)) Directory.CreateDirectory(SavePathTextBox.Text);
                    CameraHandler.StartFilming(SavePathTextBox.Text);
                }
                else CameraHandler.StartFilming();
                RecordVideoButton.Text = "Stop Video";
            }
            else
            {
                CameraHandler.StopFilming();
                RecordVideoButton.Text = "Record Video";
            }
        }

        private void BrowseButton_Click(object sender, EventArgs e)
        {
            if (Directory.Exists(SavePathTextBox.Text)) SaveFolderBrowser.SelectedPath = SavePathTextBox.Text;
            if (SaveFolderBrowser.ShowDialog() == DialogResult.OK) SavePathTextBox.Text = SaveFolderBrowser.SelectedPath;
        }

        private void AvCoBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            CameraHandler.SetSetting(EDSDK.PropID_Av, CameraValues.AV((string)AvCoBox.SelectedItem));
        }

        private void TvCoBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            CameraHandler.SetSetting(EDSDK.PropID_Tv, CameraValues.TV((string)TvCoBox.SelectedItem));
            if ((string)TvCoBox.SelectedItem == "Bulb") BulbUpDo.Enabled = true;
            else BulbUpDo.Enabled = false;
        }

        private void ISOCoBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            CameraHandler.SetSetting(EDSDK.PropID_ISOSpeed, CameraValues.ISO((string)ISOCoBox.SelectedItem));
        }

        private void WBCoBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch (WBCoBox.SelectedIndex)
            {
                case 0: CameraHandler.SetSetting(EDSDK.PropID_WhiteBalance, EDSDK.WhiteBalance_Auto); break;
                case 1: CameraHandler.SetSetting(EDSDK.PropID_WhiteBalance, EDSDK.WhiteBalance_Daylight); break;
                case 2: CameraHandler.SetSetting(EDSDK.PropID_WhiteBalance, EDSDK.WhiteBalance_Cloudy); break;
                case 3: CameraHandler.SetSetting(EDSDK.PropID_WhiteBalance, EDSDK.WhiteBalance_Tangsten); break;
                case 4: CameraHandler.SetSetting(EDSDK.PropID_WhiteBalance, EDSDK.WhiteBalance_Fluorescent); break;
                case 5: CameraHandler.SetSetting(EDSDK.PropID_WhiteBalance, EDSDK.WhiteBalance_Strobe); break;
                case 6: CameraHandler.SetSetting(EDSDK.PropID_WhiteBalance, EDSDK.WhiteBalance_WhitePaper); break;
                case 7: CameraHandler.SetSetting(EDSDK.PropID_WhiteBalance, EDSDK.WhiteBalance_Shade); break;
                case 8: CameraHandler.SetSetting(EDSDK.PropID_WhiteBalance, EDSDK.WhiteBalance_ColorTemp); break;
                case 9: CameraHandler.SetSetting(EDSDK.PropID_WhiteBalance, EDSDK.WhiteBalance_PCSet1); break;
                case 10: CameraHandler.SetSetting(EDSDK.PropID_WhiteBalance, EDSDK.WhiteBalance_PCSet2); break;
                case 11: CameraHandler.SetSetting(EDSDK.PropID_WhiteBalance, EDSDK.WhiteBalance_PCSet3); break;
            }
            if (WBCoBox.SelectedIndex == 8) WBUpDo.Enabled = true;
            else WBUpDo.Enabled = false;
        }

        private void WBUpDo_ValueChanged(object sender, EventArgs e)
        {
            CameraHandler.SetSetting(EDSDK.PropID_ColorTemperature, (uint)WBUpDo.Value);
        }

        private void SaveToButton_CheckedChanged(object sender, EventArgs e)
        {
            if (STCameraButton.Checked)
            {
                CameraHandler.SetSetting(EDSDK.PropID_SaveTo, (uint)EDSDK.EdsSaveTo.Camera);
                BrowseButton.Enabled = false;
                SavePathTextBox.Enabled = false;
            }
            else if (STComputerButton.Checked)
            {
                
                CameraHandler.SetSetting(EDSDK.PropID_SaveTo, (uint)EDSDK.EdsSaveTo.Host);
                CameraHandler.SetCapacity();
                BrowseButton.Enabled = true;
                SavePathTextBox.Enabled = true;
            }
            else if (STBothButton.Checked)
            {
                CameraHandler.SetSetting(EDSDK.PropID_SaveTo, (uint)EDSDK.EdsSaveTo.Both);
                CameraHandler.SetCapacity();
                BrowseButton.Enabled = true;
                SavePathTextBox.Enabled = true;
            }
        }
        

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            CameraHandler.Dispose();
        }


        private void CloseSession()
        {
            CameraHandler.CloseSession();
            AvCoBox.Items.Clear();
            TvCoBox.Items.Clear();
            ISOCoBox.Items.Clear();
            WBUpDo.Enabled = true;
            WBCoBox.Enabled = true;
            SettingsGroupBox.Enabled = false;
            LiveViewGroupBox.Enabled = false;
            SessionButton.Text = "Open Session";
            SessionLabel.Text = "No open session";
        }

        private void RefreshCamera()
        {
            CloseSession();
            CameraListBox.Items.Clear();
            CamList = CameraHandler.GetCameraList();
            foreach (Camera cam in CamList) CameraListBox.Items.Add(cam.Info.szDeviceDescription);
            if (CamList.Count > 0) CameraListBox.SelectedIndex = 0;
        }

        private void OpenSession()
        {
            if (CameraListBox.SelectedIndex >= 0)
            {
                CameraHandler.OpenSession(CamList[CameraListBox.SelectedIndex]);
                SessionButton.Text = "Close Session";
                string cameraname = CameraHandler.MainCamera.Info.szDeviceDescription;
                SessionLabel.Text = cameraname;
                if (CameraHandler.GetSetting(EDSDK.PropID_AEMode) != EDSDK.AEMode_Manual) MessageBox.Show("Camera is not in manual mode. Some features might not work!");
                AvList = CameraHandler.GetSettingsList((uint)EDSDK.PropID_Av);
                TvList = CameraHandler.GetSettingsList((uint)EDSDK.PropID_Tv);
                ISOList = CameraHandler.GetSettingsList((uint)EDSDK.PropID_ISOSpeed);
                foreach (int Av in AvList) AvCoBox.Items.Add(CameraValues.AV((uint)Av));
                foreach (int Tv in TvList) TvCoBox.Items.Add(CameraValues.TV((uint)Tv));
                foreach (int ISO in ISOList) ISOCoBox.Items.Add(CameraValues.ISO((uint)ISO));
                AvCoBox.SelectedIndex = AvCoBox.Items.IndexOf(CameraValues.AV((uint)CameraHandler.GetSetting((uint)EDSDK.PropID_Av)));
                TvCoBox.SelectedIndex = TvCoBox.Items.IndexOf(CameraValues.TV((uint)CameraHandler.GetSetting((uint)EDSDK.PropID_Tv)));
                ISOCoBox.SelectedIndex = ISOCoBox.Items.IndexOf(CameraValues.ISO((uint)CameraHandler.GetSetting((uint)EDSDK.PropID_ISOSpeed)));
                if (cameraname != "Canon EOS 1100D" && cameraname != "Canon EOS Rebel T3" && cameraname != "Canon EOS Kiss X50")
                {
                    int wbidx = (int)CameraHandler.GetSetting((uint)EDSDK.PropID_WhiteBalance);
                    WBCoBox.SelectedIndex = (wbidx > 8) ? wbidx - 1 : wbidx;
                    WBUpDo.Value = CameraHandler.GetSetting((uint)EDSDK.PropID_ColorTemperature);
                }
                else
                {
                    WBUpDo.Enabled = false;
                    WBCoBox.Enabled = false;
                }
                SettingsGroupBox.Enabled = true;
                LiveViewGroupBox.Enabled = true;
            }
        }
    }
}
